/* Copyright (C) 1991, 1992, 1996, 1998 Free Software Foundation, Inc.
 * This file is derived from mkstemp.c from the GNU C Library.
 *
 * $Id: mkstemps.h 3302 2010-08-09 18:39:20Z eldering $
 *
 * This file is taken from the GNU GCC libiberty library and included
 * and relicenced under the GNU GPL by the DOMjudge developers. See
 * README and COPYING for details.
 */

#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>

typedef unsigned long long gcc_uint64_t;

#ifndef TMP_MAX
#define TMP_MAX 16384
#endif

int mkstemps(char *templ, int suffix_len)
{
	static const char letters[]
		= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
	static gcc_uint64_t value;
	struct timeval tv;
	char *XXXXXX;
	size_t len;
	int count;

	len = strlen(templ);

	if ( (int) len < 6 + suffix_len ||
	     strncmp(&templ[len - 6 - suffix_len], "XXXXXX", 6)) {
		return -1;
	}

	XXXXXX = &templ[len - 6 - suffix_len];

	/* Get some more or less random data.  */
	gettimeofday(&tv, NULL);
	value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();

	for (count = 0; count < TMP_MAX; ++count) {
		gcc_uint64_t v = value;
		int fd;

		/* Fill in the random bits.  */
		XXXXXX[0] = letters[v % 62];
		v /= 62;
		XXXXXX[1] = letters[v % 62];
		v /= 62;
		XXXXXX[2] = letters[v % 62];
		v /= 62;
		XXXXXX[3] = letters[v % 62];
		v /= 62;
		XXXXXX[4] = letters[v % 62];
		v /= 62;
		XXXXXX[5] = letters[v % 62];

		fd = open(templ, O_RDWR|O_CREAT|O_EXCL, 0600);
		if (fd >= 0) return fd; /* The file did not exist. */

		/* This is a random value.  It is only necessary that the next
		   TMP_MAX values generated by adding 7777 to VALUE are different
		   with (module 2^32).  */
		value += 7777;
	}

	/* We return the null string if we can't find a unique file name.  */
	templ[0] = '\0';
	return -1;
}
